package io.gitee.devaper.starlight.common.config

import io.gitee.devaper.starlight.api.Module
import io.gitee.devaper.starlight.common.*
import org.springframework.beans.factory.BeanFactory
import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.event.ApplicationEventMulticaster
import org.springframework.context.event.SimpleApplicationEventMulticaster
import org.springframework.context.support.ResourceBundleMessageSource
import java.nio.charset.StandardCharsets
import java.util.concurrent.ExecutorService

/**
 * Spring相关的配置类
 */
@Configuration(proxyBeanMethods = false)
open class SpringConfiguration {

    /**
     * 事件广播器, Spring默认使用的是单线程的, 这里改为多线程来执行事件发布、事件监听
     *
     * @param executorService 线程池 ExecutorService
     * @param beanFactory bean工厂, ApplicationEventMulticaster需要从中找到所有的ApplicationListener
     */
    @Bean
    open fun applicationEventMulticaster(
        @Qualifier(APPLICATION_EVENT_MULTICASTER_EXECUTOR_SERVICE_BEAN_NAME) executorService: ExecutorService,
        beanFactory: BeanFactory
    ): ApplicationEventMulticaster {
        return SimpleApplicationEventMulticaster(beanFactory).apply {
            setTaskExecutor(executorService)
        }
    }

    /**
     * 消息源, 用来做国际化支持
     *
     * Spring内部存在一个MessageSource组件, 但是通过配置文件并不支持多个位置的ResourceBundle
     * 在这里自行创建一个MessageSource来载入多个位置的ResourceBundle, 每个模块的i18n信息应该放在自己模块中, 并且创建Module的实现类组件
     *
     * @param moduleList 在容器中扫描到的所有Module
     */
    @Bean
    open fun messageSource(moduleList: List<Module>) = ResourceBundleMessageSource().apply {
        setFallbackToSystemLocale(false)
        setAlwaysUseMessageFormat(false)
        setDefaultEncoding(StandardCharsets.UTF_8.name())
        // 这里将容器中所有的Module实现类messageSourceBasePaths返回的集合扁平化处理, 并载入所有的资源
        addBasenames(*moduleList.map { it.messageSourceBasePaths }.flatten().toTypedArray())
    }

}